package com.beauty.product.controller;

import com.beauty.product.dto.FileUploadResponse;
import com.beauty.product.dto.ProductImageDto;
import com.beauty.product.entity.ProductImage;
import com.beauty.product.result.Result;
import com.beauty.product.service.FileStorageService;
import com.beauty.product.service.ProductService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 商品图片控制器
 * <p>
 * 该控制器负责处理与商品图片相关的所有HTTP请求，包括图片的上传、下载、删除等操作。
 * 支持单个图片上传和批量图片上传，并提供将上传的图片关联到特定商品的功能。
 * </p>
 * 
 * @author beauty-dev
 * @version 1.0
 */
@RestController
@RequestMapping("/api/product/images")
@RequiredArgsConstructor
@Slf4j
public class ProductImageController {

    /**
     * 文件存储服务，提供文件的存储、获取和删除等基础功能
     */
    private final FileStorageService fileStorageService;
    
    /**
     * 商品服务，提供将图片关联到商品的功能
     */
    private final ProductService productService;

    /**
     * 上传单个商品图片
     * <p>
     * 接收客户端上传的单个图片文件，将其保存到服务器，并返回包含图片访问URL的响应
     * </p>
     * 
     * @param file 上传的图片文件
     * @return 返回文件上传结果，包含文件名、访问URL、文件类型和大小
     */
    @RequestMapping(method = RequestMethod.POST)
    public Result<FileUploadResponse> uploadFile(@RequestParam("file") MultipartFile file) {
        log.info("【商品服务】接收到图片上传请求: 文件名={}, 大小={}KB", file.getOriginalFilename(), file.getSize() / 1024);
        
        String fileName = fileStorageService.storeFile(file);

        String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
                .path("/api/product/images/download/")
                .path(fileName)
                .toUriString();

        FileUploadResponse response = new FileUploadResponse(
                fileName,
                fileDownloadUri,
                file.getContentType(),
                file.getSize()
        );
        
        log.info("【商品服务】图片上传成功: 保存文件名={}", fileName);
        return Result.success(response);
    }

    /**
     * 批量上传商品图片
     * <p>
     * 接收客户端上传的多个图片文件，将它们保存到服务器，并返回包含每个图片访问URL的响应列表
     * </p>
     * 
     * @param files 上传的图片文件数组
     * @return 返回批量文件上传结果列表，每项包含文件名、访问URL、文件类型和大小
     */
    @PostMapping("/upload/multiple")
    public Result<List<FileUploadResponse>> uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) {
        log.info("【商品服务】接收到批量图片上传请求: 文件数量={}", files.length);
        
        List<FileUploadResponse> responses = new ArrayList<>();
        
        Arrays.stream(files).forEach(file -> {
            String fileName = fileStorageService.storeFile(file);
            
            String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
                    .path("/api/product/images/download/")
                    .path(fileName)
                    .toUriString();
                    
            FileUploadResponse response = new FileUploadResponse(
                    fileName,
                    fileDownloadUri,
                    file.getContentType(),
                    file.getSize()
            );
            
            responses.add(response);
        });
        
        log.info("【商品服务】批量图片上传成功: 上传数量={}", responses.size());
        return Result.success(responses);
    }

    /**
     * 上传并关联商品图片
     * <p>
     * 上传图片并将其直接关联到指定的商品，自动创建商品图片记录
     * </p>
     * 
     * @param productId 商品ID
     * @param file 上传的图片文件
     * @return 返回创建的商品图片信息
     */
    @PostMapping("/product/{productId}")
    public Result<ProductImageDto> addProductImage(
            @PathVariable String productId,
            @RequestParam("file") MultipartFile file) {
        log.info("【商品服务】接收到商品[{}]图片上传请求", productId);
        
        String fileName = fileStorageService.storeFile(file);
        
        String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
                .path("/api/product/images/download/")
                .path(fileName)
                .toUriString();
        
        ProductImageDto imageDto = new ProductImageDto();
        imageDto.setProductId(productId);
        imageDto.setImageUrl(fileDownloadUri);
        imageDto.setMain(false); // 默认不是主图
        
        log.info("【商品服务】商品图片上传成功，准备添加到商品");
        return Result.success(productService.addProductImage(productId, imageDto));
    }

    /**
     * 下载商品图片
     * <p>
     * 根据文件名下载商品图片，支持浏览器直接访问或下载
     * </p>
     * 
     * @param fileName 图片文件名
     * @return 返回图片资源响应
     */
    @GetMapping("/download/{fileName:.+}")
    public ResponseEntity<Resource> downloadFile(@PathVariable String fileName) {
        try {
            log.info("【商品服务】接收到图片下载请求: 文件名={}", fileName);
            
            Path filePath = fileStorageService.getFilePath(fileName);
            Resource resource = new UrlResource(filePath.toUri());
            
            if (!resource.exists()) {
                log.error("【商品服务】文件不存在: {}", fileName);
                return ResponseEntity.notFound().build();
            }
            
            // 尝试确定文件内容类型
            String contentType = "application/octet-stream";
            
            log.info("【商品服务】图片下载成功: 文件名={}", fileName);
            return ResponseEntity.ok()
                    .contentType(MediaType.parseMediaType(contentType))
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
                    .body(resource);
        } catch (IOException ex) {
            log.error("【商品服务】图片下载失败", ex);
            return ResponseEntity.badRequest().build();
        }
    }

    /**
     * 删除商品图片
     * <p>
     * 根据文件名删除服务器上存储的商品图片文件
     * </p>
     * 
     * @param fileName 要删除的图片文件名
     * @return 返回操作结果
     */
    @DeleteMapping("/{fileName:.+}")
    public Result<Void> deleteFile(@PathVariable String fileName) {
        log.info("【商品服务】接收到图片删除请求: 文件名={}", fileName);
        fileStorageService.deleteFile(fileName);
        log.info("【商品服务】图片删除成功: 文件名={}", fileName);
        return Result.success();
    }
} 